import React, { createRef, forwardRef, PureComponent } from 'react'
import {
 Button, Form, Input, message, Modal, Spin, Tabs,
} from 'antd'
import { connect } from '@umijs/max'
import _ from 'lodash'
import { CreateDiffEditor, ProTable } from '@/components'
import { regExp } from '@/utils/regExp.js'
import EmptyPic from '@/assets/images/empty.png'
import styles from './index.less'

const { TabPane } = Tabs

const txtRe = regExp.proName(1, 128)

const resRawId = `${Math.random()}`

const PAGESIZE = 50

class TestModal extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      modalVisible: false,
      testLoading: false,
      restData: '',
      reqLog: [],
      valuesData: {},
      requestParamsData: {},
      responseParamsData: {},
      activeKey: '1',
      isSecondClick: false,
    }
    this.resRawRef = createRef()
    this.dataSourceForm = createRef()
    this.logRef = createRef()
    this.reqTableRef = createRef()
    this.timeOut = null
  }

  // useImperativeHandle(props.refInstance, () => ({
  //   toggleModal,
  // }))

  toggleModal = (values, requestParams, responseParams, pageable, apiScript) => {
    const { modalVisible } = this.state
    const requestParamsCopy = _.cloneDeep(requestParams) || []

    // 开启返回结果分页
    if (pageable === 1) {
      const pageSizeParams = {
        // ...requestParamsDataCopy[0],
        defaultValue: '10',
        paramDataType: 'INT',
        paramName: 'pageSize',
        paramRequire: 0,
        paramType: 0,
      }
      const pageNumParams = {
        // ...requestParamsDataCopy[0],
        defaultValue: '1',
        paramDataType: 'INT',
        paramName: 'pageNum',
        paramRequire: 0,
        paramType: 0,
      }

      requestParamsCopy.push(pageNumParams)
      requestParamsCopy.push(pageSizeParams)
    }

    setTimeout(() => {
      // 重置form数据
      this.dataSourceForm?.current?.resetFields()
    })

    if (modalVisible) {
      clearTimeout(this.timeOut)
      this.setState({
        testLoading: false,
        restData: '',
        reqLog: [],
        activeKey: '1',
      })
    }

    this.setState((prevState) => ({
      modalVisible: !prevState.modalVisible,
      valuesData: values,
      requestParamsData: requestParamsCopy,
      responseParamsData: responseParams,
      pageable,
      apiScript,
    }))
  }

  handleTest = () => {
    const {
      responseParamsData, requestParamsData, valuesData, pageable, apiScript,
    } = this.state
    this.dataSourceForm.current.validateFields().then(values => {
      const {
        apiDesc, apiGroupId, apiProtocol, apiPath, apiName, apiType, datasourceId, tableName,
      } = valuesData
      const requestParamsDataCopy = _.cloneDeep(requestParamsData) || []
      const responseParamsDataCopy = _.cloneDeep(responseParamsData)

      requestParamsDataCopy.map(item => { item.paramType = 0 })
      responseParamsDataCopy.map(item => { item.paramType = 1 })

      this.setState({
        testLoading: true,
        reqLog: [],
        restData: '',
      })

      const dispachType = apiType === 0 ? 'queryTestGuideApi' : 'queryTestScriptApi'

      this.props.dispatch({
        type: `myApiCreate/${dispachType}`,
        params: {
          apiDesc,
          apiGroupId,
          apiProtocol,
          apiPath,
          apiName,
          apiType,
          datasourceId,
          pageable,
          apiScript,
          tableName,
          inputParamRequest: requestParamsDataCopy,
          outputParamRequest: responseParamsDataCopy,
        },
        cb: (res) => {
          const { status, msg, data } = res
          if (status === 200) {
            this.getLogFn(data, 0)
          } else {
            this.setState({
              testLoading: false,
            })
            message.error(msg || '服务端错误')
          }
        },
      })
    })
  }

  getLogFn = (logId, offset) => {
    const { reqLog } = this.state
    this.props.dispatch({
      type: 'myApiCreate/queryLog',
      params: {
        logId,
        offset,
      },
      cb: (res) => {
        const { status, msg, data } = res
        if (status === 200) {
          this.setState(
            {
              reqLog: reqLog.concat(data?.logContent),
            },
            () => {
              // 滚动到底部
              this.logRef.current
                && (this.logRef.current.scrollTop = this.logRef.current.scrollHeight)
            },
          )

          if (!data.logEnd) {
            // 如果没有结束，每1000毫秒递归调用
            this.timeOut = setTimeout(() => {
              this.getLog(logId, data?.offset)
            }, 1000)
          } else {
            this.setState({
              testLoading: false,
              restData:
                typeof data?.result === 'string'
                  ? data?.result
                  : JSON.stringify(data.result),
            })
          }
        } else {
          this.setState({
            testLoading: false,
          })
          message.error(msg || '服务端错误')
        }
      },
    })
  }

  callback = (key) => {
    this.setState({
      activeKey: key,
      isSecondClick: key === '1',
    }, () => {
      if (this.state.isSecondClick) {
        this.setState({
          isSecondClick: false,
        })
      }
    })
  }

  getIndex = (index) => {
    // 给初始默认值
    const { pageNum = 1, pageSize = PAGESIZE } = this.reqTableRef?.current?.state || {}
    return (pageNum - 1) * pageSize + index
  }

  render() {
    const {
      modalVisible, testLoading, requestParamsData, restData, reqLog, activeKey, isSecondClick,
    } = this.state

    return (
      <Modal
        className={styles.test_modal}
        title="测试运行"
        visible={modalVisible}
        maskClosable={false}
        bodyStyle={{
          height: `${document.documentElement.clientHeight * 0.65}px`,
          overflowY: 'auto',
        }}
        width={1220}
        footer={[
          <Button key={1} onClick={this.toggleModal}>取消</Button>,
          <Button key={2} loading={testLoading} onClick={this.handleTest} type="primary">开始测试</Button>,
        ]}
        onCancel={this.toggleModal}
      >
        <div className={styles.container}>
          <div className={styles.container_left}>
            <div className={styles.container_left_title} title="请求参数">请求参数</div>
            <Form
              ref={this.dataSourceForm}
              className={styles.form}
              name="basic"
              labelCol={{ span: 5 }}
              wrapperCol={{ span: 19 }}
              initialValues={{ remember: true }}
              autoComplete="off"
            >
              <ProTable
                ref={this.reqTableRef}
                rowKey={(record) => (`${record.paramName}-${record.paramDataType}`)}
                // className={styles.table}
                columns={
                  [
                    {
                      title: '参数名称',
                      dataIndex: 'paramName',
                      width: '23%',
                    },
                    {
                      title: '参数类型',
                      dataIndex: 'paramDataType',
                      width: '23%',
                    },

                    {
                      title: '是否必填',
                      dataIndex: 'paramRequire',
                      width: '24%',
                      render: (text) => (
                        <span>{text === 1 ? '是' : '否'}</span>
                      ),
                    },
                    {
                      title: '测试值',
                      dataIndex: 'defaultValue',
                      width: '30%',
                      render: (paramName, record, index) => {
                        const realIndex = this.getIndex(index)
                        return (
                          <Form.Item
                            name={`defaultValue_${realIndex}`}
                            rules={
                              [
                                { required: record?.paramRequire, message: '请输入必填项' },
                                { pattern: new RegExp(txtRe.reg, 'g'), message: txtRe.text },
                              ]
                            }
                            initialValue={paramName}
                          >
                            <Input
                              placeholder="请输入"
                              onChange={(e) => {
                                const requestParamsDataCopy = _.cloneDeep(requestParamsData)
                                requestParamsDataCopy[realIndex].defaultValue = e.target.value
                                this.setState({
                                  requestParamsData: requestParamsDataCopy,
                                })
                              }}
                            />
                          </Form.Item>
                        )
                      },
                    },
                  ]
                }
                dataSource={requestParamsData}
                // pagination={null}
                pageSize={PAGESIZE}
                scroll={{ x: true, y: 420 }}
              />

            </Form>
          </div>
          <div className={styles.container_right}>
            <Tabs onChange={this.callback} activeKey={activeKey} type="card">
              <TabPane tab="返回结果" key="1">
                <div className={styles.json_diff_editor}>
                  <Spin spinning={testLoading}>
                    {
                      restData ? (
                        !isSecondClick && (
                          <CreateDiffEditor
                            readOnly
                            restData={restData || ''}
                            ref={this.resRawRef}
                            language="json"
                            theme="vs"
                            editorId={resRawId}
                          />
                        )
                      ) : (
                        <div className={styles.empty_box}>
                          <img src={EmptyPic} alt="" />
                          <p className={styles.note}>暂无返回结果</p>
                        </div>
                      )
                    }
                  </Spin>
                </div>
              </TabPane>
              <TabPane tab="运行日志" key="2">
                <Spin spinning={testLoading}>
                  {
                    reqLog?.length > 0 ? (
                      <div
                        className={styles.req_log_content}
                        ref={this.logRef}
                        style={{ height: '100%' }}
                      >
                        {reqLog?.join('\n')}
                      </div>
                    ) : (
                      <div className={styles.empty_box}>
                        <img src={EmptyPic} alt="" />
                        <p className={styles.note}>暂无运行日志</p>
                      </div>
                    )
                  }
                </Spin>
              </TabPane>
            </Tabs>
          </div>
        </div>

      </Modal>
    )
  }
}

class WrappedComponentRef extends PureComponent {
  render() {
    const { forwardedRef, ...rest } = this.props
    return (
      <TestModal ref={forwardedRef} {...rest} />
    )
  }
}

const IComponent = connect(({ myApiCreate }) => ({ ...myApiCreate }))(WrappedComponentRef)

export default forwardRef((props, ref) => <IComponent {...props} forwardedRef={ref} />)
